# 拉力棒推荐算法
import math
from typing import List

from seaman.core import JsonUtil

from common.params import SoftParams
from recommend.tensile.rod_common import AxialForceResult, data_init, UniForceResult


# 计算 N 弱点拉力最新计算方法
def calc_n_weak_pull(D: float, params: SoftParams, cur: AxialForceResult, F: float) -> float:
    # 电缆的单位浮重
    w2: float = params.w2
    factor_a: float = cur.azimuth_rate
    factor_b: float = math.sin(math.radians(cur.inclination))
    factor_c: float = cur.inclination_rate
    if (cur.depth > 0) and (cur.depth <= D):
        factor_d: float = F * factor_a * factor_b
        factor_e: float = F * factor_c
        n: float = math.sqrt(math.pow(factor_d, 2) + math.pow(factor_e + w2 * factor_b, 2))
        return n
    # return cur.N


# 计算 f_weak_ 最新方法
def calc_f_weak_pull(D: float, params: SoftParams, cur: AxialForceResult, pre: AxialForceResult, preN: float,
                preF: float) -> float:
    factor_b: float = math.cos(math.radians(pre.inclination))
    # 电缆的单位浮重
    w2: float = params.w2
    if (cur.depth >= 0) and (cur.depth <= D):
        f: float = w2 * factor_b + params.mu2 * preN + preF
        return f


# 计算正常上提的张力
# 计算张力
# cur 当前节点 d
# pre 上次迭代所计算的节点 d+1
# D 全井深
def calc_uni(D: float, params: SoftParams, cur: AxialForceResult, pre: AxialForceResult,
             _list_: List[AxialForceResult]) -> AxialForceResult:

    # 弱点的计算都是用上提的计算 ---> + 2 函数 calc_f_weak_pull  calc_n_weak_pull
    cur.F_weak_low = calc_f_weak_pull(D, params, cur, pre, pre.N_weak_low, pre.F_weak_low)
    cur.N_weak_low = calc_n_weak_pull(D, params, cur, cur.F_weak_low)

    cur.F_weak_high = calc_f_weak_pull(D, params, cur, pre, pre.N_weak_high, pre.F_weak_high)
    cur.N_weak_high = calc_n_weak_pull(D, params, cur, cur.F_weak_high)

    cur.F_weak_rate_low = calc_f_weak_pull(D, params, cur, pre, pre.N_weak_rate_low, pre.F_weak_rate_low)
    cur.N_weak_rate_low = calc_n_weak_pull(D, params, cur, cur.F_weak_rate_low)
    # print(JsonUtil.obj2str(cur))
    return cur


# 迭代函数
def deep_func(idx: int, params: SoftParams, _list_: List[AxialForceResult]) -> UniForceResult:
    # 迭代的最小深度
    dept_min: float = _list_[0].depth
    # 本次迭代深度
    D: float = _list_[idx].depth
    # 5种类型的点

    _list_[idx].F_weak_low = params.F_weak_low
    _list_[idx].N_weak_low = calc_n_weak_pull(D, params, _list_[idx], _list_[idx].F_weak_low)

    _list_[idx].F_weak_high = params.F_weak_high
    _list_[idx].N_weak_high = calc_n_weak_pull(D, params, _list_[idx], _list_[idx].F_weak_high)

    _list_[idx].F_weak_rate_low = params.F_weak_rate_low
    _list_[idx].N_weak_rate_low = calc_n_weak_pull(D, params, _list_[idx], _list_[idx].F_weak_rate_low)

    # 定义导出列表
    result: UniForceResult = UniForceResult()
    for i in range(idx - 1, -1, -1):
        # print(JsonUtil.obj2str(_list_[i]))
        # 迭代到一定深度，就取得最后的值

        _list_[i] = calc_uni(_list_[idx].depth, params, _list_[i], _list_[i + 1], _list_)
        result.depth = D
        result.F_weak_low = _list_[i].F_weak_low
        result.F_weak_high = _list_[i].F_weak_high
        result.F_weak_rate_low = _list_[i].F_weak_rate_low
        result.N_weak_low = _list_[i].N_weak_low
        result.N_weak_high = _list_[i].N_weak_high
        result.N_weak_rate_low = _list_[i].N_weak_rate_low

        if _list_[i].depth <= 0:
            # print(JsonUtil.obj2str(result))
            return result


# 聚合构建 返回计算结果
def uni_build(params: SoftParams, _list_: List[AxialForceResult]) -> List[UniForceResult]:
    # T 为张力
    t: List[UniForceResult] = []
    data_len = len(_list_)
    # 迭代的最小深度
    dept_min: int = int(_list_[0].depth)
    # 设置迭代次数
    # for idx in range(data_len - 1, data_len - 2, -1):
    for idx in range(data_len - 1, 0, -1):
        # if _list_[idx].depth >= params.L1 + _list_[0].depth:
        if _list_[idx].depth >= params.L1:
            # print("==========={}==============".format(idx))
            # print("从深度{}开始迭代".format(_list_[idx].depth))
            t_item: UniForceResult = deep_func(idx, params, _list_)
            # print(JsonUtil.obj2str(t_item))
            t.append(t_item)
    return t


# 定义全局 -> 中间迭代导出列表
export_depth_list = [2100.0]


# 参数 list [OilWellData]
def run(params: SoftParams, _list_) -> List[UniForceResult]:
    # 数据预处理
    result_arr: List[AxialForceResult] = data_init(_list_)
    # 计算结果
    result: List[UniForceResult] = uni_build(params, result_arr)
    return result
